<?php
/**
 * 文件缓存类。摘自{@link http://www.thinkphp.cn thinkphp}，已对源码进行修改
 *
 * @file            CacheFile.class.php
 * @package         Yap\Cache
 * @copyright       Copyright (c) 2013 {@link http://www.yaphpcms.com yaphpcms} All rights reserved
 * @license         http://www.apache.org/licenses/LICENSE-2.0.html Apache License 2.0
 * @author          liu21st <liu21st@gmail.com>
 * @date            2013-01-16 17:43:01
 * @lastmodify      $Date: 2013-01-22 05:52:40 +0000 (Tue, 22 Jan 2013) $ $Author: msl-138@163.com $
 */

namespace Yap\Cache;

/**
 * 文件缓存类。摘自{@link http://www.thinkphp.cn thinkphp}，已对源码进行修改
 *
 * @package         Yap\Cache
 * @copyright       Copyright (c) 2013 {@link http://www.yaphpcms.com yaphpcms} All rights reserved
 * @license         http://www.apache.org/licenses/LICENSE-2.0.html Apache License 2.0
 * @author          liu21st <liu21st@gmail.com>
 * @date            2013-01-16 17:43:01
 * @lastmodify      $Date: 2013-01-22 05:52:40 +0000 (Tue, 22 Jan 2013) $ $Author: msl-138@163.com $
 */
class CacheFile extends Cache {
    /**
     * @var string $_prefix 缓存文件名前缀。默认~@
     */
    protected $_prefix = '~@';

    /**
     * 取得变量的存储路径文件
     *
     * @author          liu21st <liu21st@gmail.com>
     * @lastmodify      2013-01-16 17:46:58 by mashanling
     *
     * @param string $name 缓存变量名
     *
     * @return string 变量的存储路径文件
     */
    private function filename($name) {
        $name	=	md5($name);

        if(C('DATA_CACHE_SUBDIR')) {//使用子目录
            $dir = '';
            $len = C('DATA_PATH_LEVEL');

            for($i = 0; $i < $len; $i++) {
                $dir	.=	$name{$i} . '/';
            }

            !is_dir($v = $this->_options['temp'] . $dir) && mk_dir($v, 0755, true);

            $filename	=	$dir . $this->_prefix . $name . '.php';
        }
        else{
            $filename	=	$this->_prefix . $name.'.php';
        }

        return $this->_options['temp'] . $filename;
    }

    /**
     * 构造函数
     *
     * @author          liu21st <liu21st@gmail.com>
     * @lastmodify      2013-01-16 17:47:42 by mashanling
     *
     * @param array  $options 缓存类配置数组
     *
     * @return void 无返回值
     */
    public function __construct($options = array()) {
        $this->_options = $options ? $options : $this->_options;
        $this->_options['temp'] = empty($options['temp']) ? C('DATA_CACHE_PATH') : $options['temp'];
        $this->_options['temp'] .= '/' == $this->_options['temp'] ? '' : '/';

        !is_dir($v = $this->_options['temp']) && mkdir($v, 0755, true);

        $this->_options['expire'] = isset($options['expire']) ? $options['expire'] : C('DATA_CACHE_TIME');
        $this->_options['length'] = isset($options['length']) ? $options['length'] : 0;
        $this->_connected = true;
    }

    /**
     * 清除缓存
     *
     * @author          liu21st <liu21st@gmail.com>
     * @lastmodify      2013-01-16 17:48:33 by mashanling
     *
     * @return void 无返回值
     */
    public function clear() {
        $path = $this->_options['temp'];

        if ($dir = opendir($path)) {

            while (false !== ($file = readdir($dir))) {
                !is_dir($file) && unlink( $path . $file );
            }

            closedir( $dir );
        }
    }

    /**
     * 读取指定文件名缓存
     *
     * @author          liu21st <liu21st@gmail.com>
     * @lastmodify      2013-01-16 17:49:02 by mashanling
     *
     * @param string $name 缓存变量名
     *
     * @return mixed|false 如果缓存文件存在并且有效，返回缓存内容，否则返回false
     */
    public function get($name) {
        $filename = $this->filename($name);

        if (!is_file($filename)) {
           return false;
        }

        N('cache_read', 1);

        $content = file_get_contents($filename);

        if( false !== $content) {
            $expire = intval(substr($content, 8, 12));

            if($expire && time() > filemtime($filename) + $expire) {//缓存过期删除缓存文件
                unlink($filename);
                return false;
            }

            if(C('DATA_CACHE_CHECK')) {//开启数据校验
                $check   = substr($content, 20, 32);
                $content = substr($content, 52, -3);

                if($check != md5($content)) {//校验错误
                    return false;
                }
            }
            else {
                $content = substr($content, 20, -3);
            }

            if(C('DATA_CACHE_COMPRESS') && GZCOMPRESS) {//启用数据压缩
                $content = gzuncompress($content);
            }

            return unserialize($content);
        }
        else {
            return false;
        }
    }//end get

    /**
     * 删除缓存
     *
     * @author          liu21st <liu21st@gmail.com>
     * @lastmodify      2013-01-16 17:50:28 by mashanling
     *
     * @param string $name 缓存变量名
     *
     * @return bool 删除成功，返回true，否则返回false
     */
    public function rm($name) {
        return is_file($filename = $this->filename($name)) && unlink($filename);
    }

    /**
     * 写入缓存
     *
     * @author          liu21st <liu21st@gmail.com>
     * @lastmodify      2013-01-16 17:50:28 by mashanling
     *
     * @param string $name  缓存变量名
     * @param mixed $value  存储数据
     * @param int   $expire 有效时间 0为永久
     *
     * @return bool 写入成功，返回true，否则返回false
     */
    public function set($name, $value, $expire = null) {
        N('cache_write', 1);
        $expire   = null === $expire ? $this->_options['expire'] : $expire;
        $filename = $this->filename($name);
        $data     =   serialize($value);

        if( C('DATA_CACHE_COMPRESS') && GZCOMPRESS) {//数据压缩
            $data = gzcompress($data,3);
        }

        $check  = C('DATA_CACHE_CHECK') ? md5($data) : '';//开启数据校验检测
        $data   = "<?php\n//" . sprintf('%012d', $expire) . $check . $data . "\n?>";
        $result = file_put_contents($filename, $data);

        if($result) {

            if($this->_options['length']) {//记录缓存队列
                $this->queue($name);
            }

            clearstatcache();
            return true;
        }
        else {
            return false;
        }
    }//end set
}